package db

import (
	"context"
	"log"
	"strings"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

var (
	Client *mongo.Client // 全局 MongoDB 客户端
	DBName string        // 全局数据库名
)

// Init 连接 MongoDB，并初始化 Client、DBName，
// 并确保所有索引，包括稀疏唯一的 inviteCode
func Init(uri, dbName string) {
	DBName = dbName

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
	if err != nil {
		log.Fatalf("Mongo.Connect error: %v", err)
	}
	if err := client.Ping(ctx, nil); err != nil {
		log.Fatalf("Mongo.Ping error: %v", err)
	}
	Client = client
	log.Println("✅ MongoDB connected")

	// 1) 确保 User.account 唯一索引
	userColl := Client.Database(DBName).Collection("User")
	if _, err := userColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "account", Value: 1}},
		Options: options.Index().SetName("account_1").SetUnique(true),
	}); err != nil {
		log.Fatalf("[User] 创建 account_1 索引失败: %v", err)
	} else {
		log.Println("[User] account_1 索引已存在或创建成功")
	}

	// 2) 确保 UserProfile.userId 唯一索引
	profColl := Client.Database(DBName).Collection("UserProfile")
	if _, err := profColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "userId", Value: 1}},
		Options: options.Index().SetName("userId_1").SetUnique(true),
	}); err != nil {
		log.Fatalf("[UserProfile] 创建 userId_1 索引失败: %v", err)
	} else {
		log.Println("[UserProfile] userId_1 索引已存在或创建成功")
	}

	// 3) 确保 UserProfile.inviteCode 稀疏唯一索引（跳过 null 或缺失字段）
	// 先删除旧索引（若存在）
	if _, err := profColl.Indexes().DropOne(ctx, "inviteCode_1"); err != nil {
		if !strings.Contains(err.Error(), "index not found") {
			log.Printf("[UserProfile] 删除旧 inviteCode_1 索引出错: %v", err)
		}
	}
	// 创建或确认稀疏唯一索引
	if _, err := profColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys: bson.D{{Key: "inviteCode", Value: 1}},
		Options: options.Index().
			SetName("inviteCode_1").
			SetUnique(true).
			SetSparse(true),
	}); err != nil {
		log.Fatalf("[UserProfile] 创建稀疏 inviteCode_1 索引失败: %v", err)
	} else {
		log.Println("[UserProfile] 稀疏 inviteCode_1 索引已存在或创建成功")
	}

	artColl := Client.Database(DBName).Collection("Article")
	artColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "authorId", Value: 1}},
		Options: options.Index().SetName("authorId_1"),
	})
	artColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "status", Value: 1}},
		Options: options.Index().SetName("status_1"),
	})
	artColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "visibility", Value: 1}},
		Options: options.Index().SetName("visibility_1"),
	})
	artColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "tags", Value: 1}},
		Options: options.Index().SetName("tags_1"),
	})

	// 索引：Tag.name 唯一
	tagColl := Client.Database(DBName).Collection("Tag")
	tagColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "name", Value: 1}},
		Options: options.Index().SetName("name_1").SetUnique(true),
	})

	// 索引：Comment.articleId
	commColl := Client.Database(DBName).Collection("Comment")
	commColl.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "articleId", Value: 1}},
		Options: options.Index().SetName("articleId_1"),
	})

	coll := Client.Database(DBName).Collection("categories")
	coll.Indexes().CreateOne(ctx, mongo.IndexModel{
		Keys:    bson.D{{Key: "name", Value: 1}},
		Options: options.Index().SetUnique(true),
	})

	log.Println("✅ 所有索引检查并创建完毕")
}

// Close 在程序退出时调用，用来断开连接
func Close() {
	if Client == nil {
		return
	}
	_ = Client.Disconnect(context.Background())
	log.Println("🔌 MongoDB disconnected")
}
